#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<unordered_map>
#include <boost/algorithm/string.hpp>
#include<mutex>
#include"util.hpp"
namespace ns_index
{
const std::string&DEVE="\3";
    const std::string input="data/clear/raw.txt";
struct DocInfo
{
    uint64_t id;
    std::string title;
    std::string body;
    std::string url;
};
struct Invert
{
    uint64_t id;
    std::string word;
    int weight;
};
typedef std::vector<Invert> InvertList;
class Index
{
   private:
    std::vector<DocInfo> forward;
    std::unordered_map<std::string,InvertList> Invertfind;
      
      static std::mutex mut;
       Index()
    {}
    public:
   static Index*index;
static Index*getIndex()
{
    if(index==nullptr)
    {
    mut.lock();
if(index==nullptr)
{
    index=new Index;
}
mut.unlock();
    }
return index;
}

    ~Index()
    {};
DocInfo*Getforward(const uint64_t&id)
{
if(id>=forward.size())
{
    std::cout<<"id error"<<std::endl;
    return nullptr;
}
return &forward[id];
}
InvertList*Getinvert(const std::string&word)
{
auto pos=Invertfind.find(word);
if(pos==Invertfind.end())
{
    std::cout<<"nofind"<<std::endl;
    return nullptr;
}
return &(pos->second);
}
bool BuildIndex(const std::string&path=input)
{
std::ifstream in(path,std::ios::in|std::ios::binary);
in.clear();
if(!in.is_open())
{
    std::cout<<"open error"<<std::endl;
    return false;
}
std::string line;
uint64_t id=0;
while(std::getline(in,line))
{
std::vector<std::string> an;
boost::algorithm::split(an,line,boost::is_any_of(DEVE));
DocInfo bn;
std::string name("Boost:");
bn.title=name+an[0];
bn.body=an[1];
bn.url=an[2];
bn.id=id;
 bulidInverlist(bn);
forward.push_back(std::move(bn));
if(id%50==0)
{
    std::cout<<"Number of imported files:"<<id<<std::endl;
}
id++;
}
}
bool bulidInverlist(DocInfo&bn)
{
class power
{
    public:
    int title_weight;
    int body_weight;
    power()
    :title_weight(0)
    ,body_weight(0)
    {}
};
std::vector<std::string> title_code;
util::jiebautil::CutString(bn.title,title_code);
std::unordered_map<std::string,power>all;
int count=0;
for(auto&e:title_code)
{
    boost::to_lower(e);
all[e].title_weight++;

}
std::vector<std::string> body_code;
util::jiebautil::CutString(bn.body,body_code);
count=0;
for(auto&e:body_code)
{
     boost::to_lower(e);
    all[e].body_weight++;

}
count=0;
for(auto&power_pair:all)
{
int X=40;
int Y=1;
    Invert an;
    an.id=bn.id;
    an.word=power_pair.first;
    an.weight=power_pair.second.title_weight*X+power_pair.second.body_weight*Y;
    InvertList&invertlist=Invertfind[an.word];
    invertlist.push_back(std::move(an));

}
return true;
}
};
Index*Index::index=nullptr;
std::mutex Index::mut;
}
